﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using SCRUM.Core.BusinessObjects;
using SCRUM.Core.DAO;
using System.Collections.Specialized;
using SCRUM.Core.MembershipProviders;
using AjaxControlToolkit;

/// <summary>
/// Widget displays Sprints, User stories, Backlog items and Tasks in file system like structure with possibility to browse underlying levels.
/// User may browse the hierarchy and display all subentities for choosen entity, return to parent entity
/// and perform create, update, delete operations on all of the entities while his role is Scrum master or Standard team member.
/// Product owner has only read access.
/// </summary>
public partial class Sprint2Widget : WidgetBase
{

    public override string Title
    {
        get { return (string)GetLocalResourceObject("Title"); }
    }

    public override bool IsEditable
    {
        get { return true; }
    }

    /// <summary>
    /// Gets the name of the widget. It must be exactly the same as the folder that contains the widget.
    /// </summary>
    /// <value></value>
    public override string Name
    {
        get { return "Sprint2Widget"; }
    }

    private IList<Sprint> sprints;
    private IList<UserStory> userStories;
    private IList<BLI> blis;
    private List<Task> tasks;
    private ColumnDef columns;

    private User user;
    private Widget widget;

    private bool isUserStory = false;
    private bool isBli = false;
    private bool isTask = false;

    private Sprint inSprint;
    private UserStory inUserStory;
    private BLI inBli;

    private StringDictionary settings;

    /// <summary>
    /// This method works as a substitute for Page_Load. You should use this method for
    /// data binding etc. instead of Page_Load.
    /// </summary>
    public override void LoadWidget()
    {
        //load settings for widget/user
        settings = GetSettings();
        Up.Visible = false;
        userStories = null;
        blis = null;
        tasks = null;
        sprints = DAOSprint.GetAllSprints();

        //there is a user setting for project columns
        if (settings.ContainsKey("sprintColumnDef"))
        {
            columns = new ColumnDef(ColumnDef.sprint, settings["sprintColumnDef"]);
        }
        else
        {
            //or use default
            columns = new ColumnDef(ColumnDef.sprint);
        }

        //set default visibility
        SprintsLbl.Visible = true;
        UserStoriesLbl.Visible = false;
        BlisLbl.Visible = false;
        TasksLbl.Visible = false;

        SprintsCB.Visible = false;
        UserStoriesCB.Visible = false;
        BlisCB.Visible = false;

        //load UserStories if needed
        loadUserStoriesAccordingToUserSettings();

        //load blis if needed
        loadBlisAccordingToUserSettings();

        //load tasks if needed
        loadTasksAccordingToUserSettings();

        generateColumnDef();
        //according to column definition create columns in AllData grid
        generateColumns();
        //choose datasource for AllData grid
        if (tasks != null)
        {
            AllData.DataSource = tasks;
        }
        else if (blis != null)
        {
            createGoColumn("GoTask");
            AllData.DataSource = blis;
        }
        else if (userStories != null)
        {
            createGoColumn("GoBli");
            AllData.DataSource = userStories;
        }
        else
        {
            AllData.DataSource = sprints;
            createGoColumn("GoUserStory");
        }
        try
        {
            AllData.DataBind();
        }
        catch
        {
            //throw new Exception("Column def does not fit!");
        }
    }

    /// <summary>
    /// Loads tasks if selectedBliId is in settings, means user selected some bli
    /// and all its tasks should be displayed
    /// </summary>
    private void loadTasksAccordingToUserSettings()
    {
        //user selected Bli - load all tasks for selected bli
        if (settings.ContainsKey("selectedBliId"))
        {
            int bliId = System.Convert.ToInt32(settings["selectedBliId"]);
            inBli = DAOBli.GetBliByID(bliId);

            SprintsLbl.Visible = false;
            UserStoriesLbl.Visible = false;
            BlisLbl.Visible = false;
            TasksLbl.Visible = true;
            
            tasks = DAOTask.GetAllTasksForBli(inBli);
            try{
            BlisCB.DataSource = blis;
            BlisCB.SelectedIndex = -1;
            BlisCB.DataBind();

            if (inBli != null)
            {
                    BlisCB.SelectedValue = inBli.ID.ToString();
            }
            BlisCB.Visible = true;

            }
            catch (Exception e)
            {
                DAOWidgetSettings.DeleteSetting(widget, "SelectedTaskId");
                DAOWidgetSettings.DeleteSetting(widget, "SelectedBliId");
                LoadWidget();
            }
            Up.Visible = true;
            //mark that blis are visible
            isTask = true;
            if (settings.ContainsKey("taskColumnDef"))
            {
                columns = new ColumnDef(ColumnDef.task, settings["taskColumnDef"]);
            }
            else
            {
                columns = new ColumnDef(ColumnDef.task);
            }
        }
    }

    /// <summary>
    /// Loads blis if selectedUserStoryId is in settings, means user selected some user story
    /// and all its blis should be displayed
    /// </summary>
    private void loadBlisAccordingToUserSettings()
    {
        //user selected release - load all sprints for selected release
        if (settings.ContainsKey("selectedUserStoryId"))
        {
            int userStoryId = System.Convert.ToInt32(settings["selectedUserStoryId"]);
            inUserStory = DAOUserStory.GetUserStoryByID(userStoryId);

            SprintsLbl.Visible = false;
            UserStoriesLbl.Visible = false;
            BlisLbl.Visible = true;
            TasksLbl.Visible = false;
            blis = DAOBli.GetAllBlisForUserStory(userStoryId);

            UserStoriesCB.DataSource = userStories;
            UserStoriesCB.SelectedIndex = -1;
            UserStoriesCB.DataBind();
            if (inUserStory != null)
            {
                UserStoriesCB.SelectedValue = inUserStory.ID.ToString();
            }
            UserStoriesCB.Visible = true;
            Up.Visible = true;
            //mark that blis are visible
            isBli = true;
            if (settings.ContainsKey("bliColumnDef"))
            {
                columns = new ColumnDef(ColumnDef.bli, settings["bliColumnDef"]);
            }
            else
            {
                columns = new ColumnDef(ColumnDef.bli);
            }
        }
    }

    /// <summary>
    /// Loads user stories if selectedSprintId is in settings, means user selected some sprint
    /// and all its user stories should be displayed
    /// </summary>
    private void loadUserStoriesAccordingToUserSettings()
    {
        //there is a setting that project was selected - means to load all releases for this project
        if (settings.ContainsKey("SelectedSprintId"))
        {
            int sprintId = System.Convert.ToInt32(settings["SelectedSprintId"]);
            inSprint = DAOSprint.GetSprintById(sprintId);
            SprintsLbl.Visible = false;
            UserStoriesLbl.Visible = true;
            BlisLbl.Visible = false;
            TasksLbl.Visible = false;
            userStories = DAOUserStory.GetAllUserStoriesForSprint(sprintId);

            SprintsCB.DataSource = sprints;
            SprintsCB.DataBind();
            SprintsCB.SelectedValue = inSprint.ID.ToString();
            SprintsCB.Visible = true;
            Up.Visible = true;
            //mark that releases are visible
            isUserStory = true;
            //there is a setting for column definition 
            if (settings.ContainsKey("userStoryColumnDef"))
            {
                columns = new ColumnDef(ColumnDef.userStory, settings["userStoryColumnDef"]);
            }
            else
            {
                //show default setting
                columns = new ColumnDef(ColumnDef.userStory);
            }
        }
    }

    /// <summary>
    /// Creates columns based on column definition and adds them to AddData grid
    /// </summary>
    private void generateColumns()
    {
        AllData.Columns.Clear();
        foreach (String key in columns.Columns.Keys.ToArray<String>())
        {
            ButtonField column = new ButtonField();
            column.CommandName = "NameClicked";
            column.Visible = columns.Columns[key];
            column.HeaderText = (string)GetLocalResourceObject(key);
            column.DataTextField = key;
            AllData.Columns.Add(column);
        }
    }

    /// <summary>
    /// Creates column with specific command name
    /// </summary>
    /// <param name="commandName">Command name</param>
    private void createGoColumn(string commandName)
    {
        ButtonField column1 = new ButtonField();
        column1.CommandName = commandName;
        column1.Visible = true;
        column1.HeaderText = (string)GetLocalResourceObject("GO");
        column1.Text = (string)GetLocalResourceObject("GO!");
        AllData.Columns.Add(column1);
    }

    /// <summary>
    /// Creates column definition for AddData grid and shows them to DivEdit
    /// </summary>
    private void generateColumnDef()
    {
        List<OrderedColumn> finalList = new List<OrderedColumn>();
        if (HttpContext.Current.Session["Sprint2WidgetCD" + this.ID] == null)
        {
            List<OrderedColumn> enabledList = new List<OrderedColumn>();
            List<OrderedColumn> disabledList = new List<OrderedColumn>();
            foreach (String key in columns.Columns.Keys)
            {
                if (columns.Columns[key])
                {
                    enabledList.Add(new OrderedColumn(key.ToString()));
                }
                else
                {
                    disabledList.Add(new OrderedColumn(key.ToString()));
                }
            }

            finalList.AddRange(enabledList);
            finalList.Add(new OrderedColumn("-- ^Enabled, V Disabled --"));
            finalList.AddRange(disabledList);
        }
        else
        {
            try
            {
                finalList = (List<OrderedColumn>)HttpContext.Current.Session["Sprint2WidgetCD" + this.ID];
            }
            catch (InvalidCastException e)
            {
                //change this 
                HttpContext.Current.Session["Sprint2WidgetCD" + this.ID] = null;
                LoadWidget();
            }
        }

        ReorderColumns.DataSource = finalList;
        ReorderColumns.DataBind();
    }

    /// <summary>
    /// Method to catch all commands on the AllData grid.
    /// </summary>
    /// <param name="sender">sender</param>
    /// <param name="e">command arguments - name, selected row,...</param>
    public void handleRowCommand(Object sender, GridViewCommandEventArgs e)
    {
        // If multiple ButtonField column fields are used, use the
        // CommandName property to determine which button was clicked.
        //command to highlight row and show details of selected entity
        if (e.CommandName == "NameClicked")
        {
            hideAllDetails();
            //returns selected row
            int row = System.Convert.ToInt32(e.CommandArgument);
            if (row != -1)
            {
                if (isTask)
                {
                    //show task detail
                    TaskDataDetails.AvailableSuperiorItems = blis;
                    TaskDataDetails.DisplayItem(tasks.ElementAt(row));
                }
                else if (isBli)
                {
                    //show release detail
                    BliDataDetails.AvailableSuperiorItems = userStories;
                    BliDataDetails.SuperiorItemID = inUserStory.ID;
                    BliDataDetails.DisplayItem(blis.ElementAt(row));
                }
                else if (isUserStory)
                {
                    //show release detail
                    UserStoryDataDetails.AvailableSuperiorItems = sprints;
                    UserStoryDataDetails.SuperiorItemID = inSprint.ID;
                    UserStoryDataDetails.DisplayItem(userStories.ElementAt(row));
                }
                else
                {
                    List<Release> rels = new List<Release>();
                    Release inRel = DAORelease.GetReleaseBySprintID(sprints.ElementAt(row).ID);
                    rels.Add(inRel);
                    SprintDataDetails.AvailableSuperiorItems = rels;
                    SprintDataDetails.SuperiorItemID = inRel.ID;
                    SprintDataDetails.DisplayItem(sprints.ElementAt(row));
                }
                AllData.SelectedIndex = row;
                OkDiv.Visible = true;
                EditBtn.Visible = true;
                OkBtn.Visible = false;
                DeleteBtn.Visible = true;
            }
        }
        //command to show all userstories for selected sprint 
        else if (e.CommandName == "GoUserStory")
        {
            AllData.SelectedIndex = System.Convert.ToInt32(e.CommandArgument);

            widget = DAOWidget.GetWidgetByID(this.ID);
            DAOWidgetSettings.SaveCreateSettings(widget, "SelectedSprintId", sprints[System.Convert.ToInt32(e.CommandArgument)].ID.ToString());
            hideAllDetails();
            HttpContext.Current.Session["Sprint2WidgetCD" + this.ID] = null;
            LoadWidget();

        }
        //command to show all blis for selected user story
        else if (e.CommandName == "GoBli")
        {
            AllData.SelectedIndex = System.Convert.ToInt32(e.CommandArgument);
            widget = DAOWidget.GetWidgetByID(this.ID);
            DAOWidgetSettings.SaveCreateSettings(widget, "SelectedUserStoryId", userStories[System.Convert.ToInt32(e.CommandArgument)].ID.ToString());
            hideAllDetails();
            HttpContext.Current.Session["Sprint2WidgetCD" + this.ID] = null;
            LoadWidget();
        }
        //command to show all tasks for selected bli
        else if (e.CommandName == "GoTask")
        {
            AllData.SelectedIndex = System.Convert.ToInt32(e.CommandArgument);
            widget = DAOWidget.GetWidgetByID(this.ID);
            DAOWidgetSettings.SaveCreateSettings(widget, "SelectedBliId", blis[System.Convert.ToInt32(e.CommandArgument)].ID.ToString());
            hideAllDetails();
            HttpContext.Current.Session["Sprint2WidgetCD" + this.ID] = null;
            LoadWidget();
        }

    }

    /// <summary>
    /// Shows the edit.
    /// </summary>
    public override void ShowEdit()
    {
        DivEdit.Visible = true;
    }

    /// <summary>
    /// Hides the edit.
    /// </summary>
    public override void HideEdit()
    {
        DivEdit.Visible = false;
    }

    /// <summary>
    /// Saves settings from DivEdit and hides edit.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void LinkButtonSave_Click(object sender, EventArgs e)
    {
        //save config
        saveColumnDefSetting();
        hideAllDetails();
        LoadWidget();
    }

    /// <summary>
    /// Creates new settings for column definition and saves it
    /// </summary>
    private void saveColumnDefSetting()
    {
        string type = "";
        if (isTask)
        {
            type = "taskColumnDef";
        }
        else if (isBli)
        {
            type = "bliColumnDef";
        }
        else if (isUserStory)
        {
            type = "userStoryColumnDef";
        }
        else
        {
            type = "sprintColumnDef";
        }
        string settings = "";
        List<OrderedColumn> cols = (List<OrderedColumn>)HttpContext.Current.Session["Sprint2WidgetCD" + this.ID];
        if (cols != null)
        {
            bool visible = true;
            bool line;
            foreach (OrderedColumn col in cols)
            {
                line = false;
                if (col.Data.StartsWith("--"))
                {
                    visible = false;
                    line = true;
                }
                if (!line)
                {
                    settings = settings + col.Data + ":" + visible.ToString() + ";";
                }
            }
        }

        if (!settings.Equals("") && !type.Equals(""))
        {
            widget = DAOWidget.GetWidgetByID(this.ID);
            DAOWidgetSettings.SaveCreateSettings(widget, type, settings);
        }

    }

    /// <summary>
    /// Column definition order changed
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void ReorderColumns_ItemReorder(object sender,
          AjaxControlToolkit.ReorderListItemReorderEventArgs e)
    {
        //Item Reordered, so save the current order to the Session scope
        HttpContext.Current.Session["Sprint2WidgetCD" + this.ID] = ReorderColumns.DataSource;

    }

    /// <summary>
    /// Shows one level up entities in hierarchy: project, release, sprint.
    /// Stores this user setting for this widget.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void Up_Click(object sender, EventArgs e)
    {
        widget = DAOWidget.GetWidgetByID(this.ID);
        if (isTask)
        {
            DAOWidgetSettings.DeleteSetting(widget, "SelectedBliId");
        }
        else if (isBli)
        {
            DAOWidgetSettings.DeleteSetting(widget, "SelectedUserStoryId");
        }
        else if (isUserStory)
        {
            DAOWidgetSettings.DeleteSetting(widget, "SelectedSprintId");
        }
        hideAllDetails();
        HttpContext.Current.Session["Sprint2WidgetCD" + this.ID] = null;
        LoadWidget();
    }

    /// <summary>
    /// Change data in Alldata grid according to selection in combobox, for sprints
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void SprintsCB_SelectedIndexChanged(object sender, EventArgs e)
    {
        widget = DAOWidget.GetWidgetByID(this.ID);
        DAOWidgetSettings.DeleteSetting(widget, "SelectedUserStoryId");
        DAOWidgetSettings.DeleteSetting(widget, "SelectedBliId");
        DAOWidgetSettings.SaveCreateSettings(widget, "SelectedSprintId",
             SprintsCB.SelectedValue.ToString());
        HttpContext.Current.Session["Sprint2WidgetCD" + this.ID] = null;
        hideAllDetails();
        LoadWidget();

    }

    /// <summary>
    /// Change data in Alldata grid according to selection in combobox, for user stories
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void UserStoriesCB_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (UserStoriesCB.Visible)
        {
            widget = DAOWidget.GetWidgetByID(this.ID);
            DAOWidgetSettings.DeleteSetting(widget, "SelectedBliId");
            DAOWidgetSettings.SaveCreateSettings(widget, "SelectedUserStoryId",
                     UserStoriesCB.SelectedValue.ToString());
            HttpContext.Current.Session["Sprint2WidgetCD" + this.ID] = null;
            hideAllDetails();
            LoadWidget();
        }
    }

    /// <summary>
    /// Change data in Alldata grid according to selection in combobox, for bli
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void BlisCB_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (BlisCB.Visible)
        {
            widget = DAOWidget.GetWidgetByID(this.ID);
            DAOWidgetSettings.SaveCreateSettings(widget, "SelectedBliId",
                     BlisCB.SelectedValue.ToString());
            HttpContext.Current.Session["Sprint2WidgetCD" + this.ID] = null;
            hideAllDetails();
            LoadWidget();
        }
    }

    /// <summary>
    /// Hides all detail divs
    /// </summary>
    private void hideAllDetails()
    {
        UserStoryDataDetails.Visible = false;
        BliDataDetails.Visible = false;
        TaskDataDetails.Visible = false;
        SprintDataDetails.Visible = false;
        OkDiv.Visible = false;
        AllData.SelectedIndex = -1;
    }

    /// <summary>
    /// Creates new entity
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void CreateBtn_Click(object sender, EventArgs e)
    {
        if (isTask)
        {
            //show task detail
            TaskDataDetails.AvailableSuperiorItems = blis;
            TaskDataDetails.SuperiorItemID = inBli.ID;
            TaskDataDetails.SelectedItem = null;
        }
        else if (isBli)
        {
            //show release detail
            BliDataDetails.AvailableSuperiorItems = userStories;
            BliDataDetails.SuperiorItemID = inUserStory.ID;
            BliDataDetails.SelectedItem = null;
        }
        else if (isUserStory)
        {
            //show release detail
            UserStoryDataDetails.AvailableSuperiorItems = sprints;
            UserStoryDataDetails.SuperiorItemID = inSprint.ID;
            UserStoryDataDetails.SelectedItem = null;
        }
        else
        {
            IList<Release> rels = DAORelease.GetAllReleases();
            SprintDataDetails.AvailableSuperiorItems = rels;
            SprintDataDetails.SelectedItem = null;
        }
        OkDiv.Visible = true;
        EditBtn.Visible = false;
        OkBtn.Visible = true;
        DeleteBtn.Visible = false;
    }

    /// <summary>
    /// Updates selected entity
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void EditBtn_Click(object sender, EventArgs e)
    {
        if (AllData.SelectedIndex != -1)
        {
            if (isTask)
            {
                Task tskOld = (Task)tasks[AllData.SelectedIndex];
                TaskDataDetails.EditItem(tskOld.ID);
                TaskDataDetails.Visible = false;
            }
            else if (isBli)
            {
                BLI bliOld = (BLI)blis[AllData.SelectedIndex];
                BliDataDetails.EditItem(bliOld.ID);
                BliDataDetails.Visible = false;
            }
            else if (isUserStory)
            {
                UserStory usOld = (UserStory)userStories[AllData.SelectedIndex];
                UserStoryDataDetails.EditItem(usOld.ID);
                UserStoryDataDetails.Visible = false;
            }
            else
            {
                Sprint sprOld = (Sprint)sprints[AllData.SelectedIndex];
                SprintDataDetails.EditItem(sprOld.ID);
                SprintDataDetails.Visible = false;
            }
            LoadWidget();
            hideAllDetails();
        }
    }

    /// <summary>
    /// Deletes selected entity
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void DeleteBtn_Click(object sender, EventArgs e)
    {
        if (AllData.SelectedIndex != -1)
        {
            if (isTask)
            {
                TaskDataDetails.DeleteItem(tasks[AllData.SelectedIndex]);
            }
            else if (isBli)
            {
                BliDataDetails.DeleteItem(blis[AllData.SelectedIndex]);
            }
            else if (isUserStory)
            {
                UserStoryDataDetails.DeleteItem(userStories[AllData.SelectedIndex]);
            }
            else
            {
                SprintDataDetails.DeleteItem(sprints[AllData.SelectedIndex]);
            }
            hideAllDetails();
            LoadWidget();
        }
    }

    /// <summary>
    /// Confirmed createion of new entity
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void OkBtn_Click(object sender, EventArgs e)
    {
        if (isTask)
        {
            Task tsk = TaskDataDetails.CreateItem();
        }
        else if (isBli)
        {
            BLI bli = BliDataDetails.CreateItem();
        }
        else if (isUserStory)
        {
            UserStory us = UserStoryDataDetails.CreateItem();
        }
        else
        {
            Sprint spr = SprintDataDetails.CreateItem();
        }
        hideAllDetails();
        LoadWidget();
    }

    /// <summary>
    /// User pressed cancel button
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void CancelBtn_Click(object sender, EventArgs e)
    {
        hideAllDetails();
    }
    /// <summary>
    /// Paging changed
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void AllData_PageIndexChanging(object sender, GridViewPageEventArgs e)
    {
        AllData.PageIndex = e.NewPageIndex;
        AllData.DataBind();
    }
}
